﻿
namespace Accord.MachineLearning
{
    using System;
    
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Accord.Math;
    using System.Collections.ObjectModel;

    public class myKmeans
    {
        int[] clusterScatter;
        double[][] imagePixel;
        int kNum;
        double lamda;

        public myKmeans(int k,int[] scat, double[][] pxl,double lamda)
        {
            this.clusterScatter = scat;
            this.imagePixel = pxl;
            this.kNum = k;
            this.lamda = lamda;
        }

        public double[,] setAinIterationI()
        {
            double[,] clusterJResult=new double[3,3];
            for (int i = 0; i < this.kNum; i++)
                 clusterJResult =clusterJResult.addition(setClusterJinIterationI(i, this.clusterScatter, this.imagePixel,lamda));
            
            return clusterJResult;
        }
        public double[,] setClusterJinIterationI(int iteration,int[]clusters,double[][]pixel,double lamda)
        {
            double[,] mean =calculateClusterMean(iteration, clusters, pixel);
            double[,] cov=calculateClusterCovariance(iteration,clusters,pixel,mean);
            double[,] A = mean.MultiplyMatrix(mean.Transpose());                        //  mean*mean^T
            double[,] B = A.multiplyMatrixByNumber(lamda);                              //lamda*mean*mean^T
            int clusterSize = calculateClusterSize(iteration, clusters);
            double C = lamda + clusterSize;
            double[,] D = A.devideMatrixByNumber(C);                          //  mean*mean^T/cluster size
            double[,] E = cov.addition(D);                                              //  covariance+mean*mean^T/cluster size
            double[,] F = E.multiplyMatrixByNumber(clusterSize);

            return F;

        }
        public int calculateClusterSize(int iteration,int[]clusters)
        {
            int amount=0;
            for (int i = 0; i < clusters.Length; i++)
                if (clusters[i] == iteration)
                    amount++;

            return amount;
        }

        public double[,] calculateClusterMean(int iteration, int []clusters,double[][]pxl)
        {
            int size = calculateClusterSize(iteration, clusters);
            double[,] sumPixelInCluster = new double[3, 1];
            if (size == 0) return sumPixelInCluster;

            for (int i = 0; i < clusters.Length; i++)
                if (clusters[i] == iteration)
                    for (int j = 0; j < 3; j++)
                        sumPixelInCluster[j,0] += pxl[i][j];
                       

            for (int j = 0; j < 3; j++)
                sumPixelInCluster[j,0] /= size;

            return sumPixelInCluster;
        }

       public double[,] calculateClusterCovariance(int iteration, int[] clusters, double[][] pxl,double[,]mean)
        {
            int size = calculateClusterSize(iteration, clusters);
           double[,] pixelDiffer = new double[3,1];
           double[,] sumCov = new double[3, 3];
           if (size == 0) return sumCov;

            for (int i = 0; i < clusters.Length; i++)
                if (clusters[i] == iteration)  
                {
                    for (int j = 0; j < 3; j++)
                    {  
                        double diff= pxl[i][j] - mean[j,0];        //[Xr-mean]
                        pixelDiffer[j,0] = diff; 
                    }
                    double[,] sum = pixelDiffer.MultiplyMatrix(pixelDiffer.Transpose());
                    sumCov.addition(sum);   
                }

            return sumCov;
        }

    }
}
